We are migrating the bug tracker to github Issues. This is now the preferred way to report NASM bugs.

Self-registration is disabled due to spam issue (mail gorcunov@gmail.com or hpa@zytor.com to create an account)

Bug 3392623 - git nasm: %xdefine macro(a) (a) expands a
Summary: git nasm: %xdefine macro(a) (a) expands a
Status: CLOSED FIXED
Alias: None
Product: NASM
Classification: Unclassified
Component: Assembler (show other bugs)
Version: 2.15.xx
Hardware: All All
: Medium severe
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2019-10-15 05:50 PDT by E. C. Masloch
Modified: 2019-10-24 00:50 PDT (History)
5 users (show)

Obtained from: Built from git using configure
Generated by: ---
Bug category:
Observed for: ---
Regression: ---
Regression since:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description E. C. Masloch 2019-10-15 05:50:37 PDT
The version of nasm here is https://repo.or.cz/nasm.git/commitdiff/d03a6c8ffedd1496221eca5f02ba0215794cfaf9 plus the patch given in https://bugzilla.nasm.us/show_bug.cgi?id=3392599#c11

The test.asm contents are lifted directly from https://hg.ulukai.org/ecm/lmacros/file/67a2ee517d8e/lmacros1.mac  test2.asm contains a workaround that uses %define instead of %xdefine.

The problem is that I used d as a single-line macro parameter in the _Xdigits macros, which are specified with %xdefine, but d is also %idefine to dword. The new preprocessor expands this d in the %xdefine line to dword, whereas older preprocessors don't.


$ nasm -v
NASM version 2.15rc0 compiled on Oct 10 2019
$ cat test.asm
%idefine d dword

%define _1digits_nocheck(d)     (((d)% 10)+'0')
%xdefine _1digits(d)    (!!(d/10)*(1<<32)+  _1digits_nocheck(d))

db _1digits(8)
$ nasm test.asm
test.asm:6: error: expression syntax error
$ nasm -Ls -Lp -l test.lst test.asm
test.asm:6: error: expression syntax error
$ cat test.lst
     0                                   ;;; %define __?FILE?__
     0                                   ;;; %define __?LINE?__
     0                                   ;;; %define __?BITS?__
     0                                   ;;; %define __?PTR?__
     0                                   ;;; %define __?PASS?__ 1
     0                                   ;;; %define __?SECT?__
     0                                   ;;; %defalias __SECT__ __?SECT?__
     0                                   ;;; %define __?SECTALIGN_ALIGN_UPDATES_SECTION?__ 1
     0                                   ;;; %defalias __SECTALIGN_ALIGN_UPDATES_SECTION__ __?SECTALIGN_ALIGN_UPDATES_SECTION?__
     0                                   ;;; %define __?FLOAT_DAZ?__ nodaz
     0                                   ;;; %define __?FLOAT_ROUND?__ near
     0                                   ;;; %define __?FLOAT?__ __?FLOAT_DAZ?__,__?FLOAT_ROUND?__
     0                                   ;;; %defalias __FLOAT_DAZ__ __?FLOAT_DAZ?__
     0                                   ;;; %defalias __FLOAT_ROUND__ __?FLOAT_ROUND?__
     0                                   ;;; %defalias __FLOAT__ __?FLOAT?__
     0                                   ;;; %defalias __NASM_MAJOR__ __?NASM_MAJOR?__
     0                                   ;;; %defalias __NASM_MINOR__ __?NASM_MINOR?__
     0                                   ;;; %defalias __NASM_SUBMINOR__ __?NASM_SUBMINOR?__
     0                                   ;;; %defalias __NASM_PATCHLEVEL__ __?NASM_PATCHLEVEL?__
     0                                   ;;; %defalias __NASM_SNAPSHOT__ __?NASM_SNAPSHOT?__
     0                                   ;;; %defalias __NASM_VERSION_ID__ __?NASM_VERSION_ID?__
     0                                   ;;; %defalias __NASM_VER__ __?NASM_VER?__
     0                                   ;;; %defalias __OUTPUT_FORMAT__ __?OUTPUT_FORMAT?__
     0                                   ;;; %defalias __DEBUG_FORMAT__ __?DEBUG_FORMAT?__
     0                                   ;;; %defalias __DATE__ __?DATE?__
     0                                   ;;; %defalias __DATE_NUM__ __?DATE_NUM?__
     0                                   ;;; %defalias __TIME__ __?TIME?__
     0                                   ;;; %defalias __TIME_NUM__ __?TIME_NUM?__
     0                                   ;;; %defalias __UTC_DATE__ __?UTC_DATE?__
     0                                   ;;; %defalias __UTC_DATE_NUM__ __?UTC_DATE_NUM?__
     0                                   ;;; %defalias __UTC_TIME__ __?UTC_TIME?__
     0                                   ;;; %defalias __UTC_TIME_NUM__ __?UTC_TIME_NUM?__
     0                                   ;;; %defalias __POSIX_TIME__ __?POSIX_TIME?__
     0                                   ;;; %defalias __FILE__ __?FILE?__
     0                                   ;;; %defalias __LINE__ __?LINE?__
     0                                   ;;; %defalias __BITS__ __?BITS?__
     0                                   ;;; %defalias __PTR__ __?PTR?__
     0                                   ;;; %defalias __PASS__ __?PASS?__
     0                                   ;;; %idefine __?infinity?__ %?
     0                                   ;;; %idefine __?nan?__ %?
     0                                   ;;; %idefine __?qnan?__ %?
     0                                   ;;; %idefine __?snan?__ %?
     0                                   ;;; %idefine __?float8?__ %?
     0                                   ;;; %idefine __?float16?__ %?
     0                                   ;;; %idefine __?float32?__ %?
     0                                   ;;; %idefine __?float64?__ %?
     0                                   ;;; %idefine __?float80m?__ %?
     0                                   ;;; %idefine __?float80e?__ %?
     0                                   ;;; %idefine __?float128l?__ %?
     0                                   ;;; %idefine __?float128h?__ %?
     0                                   ;;; %idefine __?utf16?__ %?
     0                                   ;;; %idefine __?utf16le?__ %?
     0                                   ;;; %idefine __?utf16be?__ %?
     0                                   ;;; %idefine __?utf32?__ %?
     0                                   ;;; %idefine __?utf32le?__ %?
     0                                   ;;; %idefine __?utf32be?__ %?
     0                                   ;;; %idefine __?ilog2e?__ %?
     0                                   ;;; %idefine __?ilog2w?__ %?
     0                                   ;;; %idefine __?ilog2f?__ %?
     0                                   ;;; %idefine __?ilog2c?__ %?
     0                                   ;;; %idefalias __infinity__ __?infinity?__
     0                                   ;;; %idefalias __nan__ __?nan?__
     0                                   ;;; %idefalias __qnan__ __?qnan?__
     0                                   ;;; %idefalias __snan__ __?snan?__
     0                                   ;;; %idefalias __float8__ __?float8?__
     0                                   ;;; %idefalias __float16__ __?float16?__
     0                                   ;;; %idefalias __float32__ __?float32?__
     0                                   ;;; %idefalias __float64__ __?float64?__
     0                                   ;;; %idefalias __float80m__ __?float80m?__
     0                                   ;;; %idefalias __float80e__ __?float80e?__
     0                                   ;;; %idefalias __float128l__ __?float128l?__
     0                                   ;;; %idefalias __float128h__ __?float128h?__
     0                                   ;;; %idefalias __utf16__ __?utf16?__
     0                                   ;;; %idefalias __utf16le__ __?utf16le?__
     0                                   ;;; %idefalias __utf16be__ __?utf16be?__
     0                                   ;;; %idefalias __utf32__ __?utf32?__
     0                                   ;;; %idefalias __utf32le__ __?utf32le?__
     0                                   ;;; %idefalias __utf32be__ __?utf32be?__
     0                                   ;;; %idefalias __ilog2e__ __?ilog2e?__
     0                                   ;;; %idefalias __ilog2w__ __?ilog2w?__
     0                                   ;;; %idefalias __ilog2f__ __?ilog2f?__
     0                                   ;;; %idefalias __ilog2c__ __?ilog2c?__
     0                                   ;;; %define __?NASM_MAJOR?__ 2
     0                                   ;;; %define __?NASM_MINOR?__ 14
     0                                   ;;; %define __?NASM_SUBMINOR?__ 99
     0                                   ;;; %define __?NASM_PATCHLEVEL?__ 90
     0                                   ;;; %define __?NASM_VERSION_ID?__ 0020E635Ah
     0                                   ;;; %define __?NASM_VER?__ "2.15rc0"
     0                                   ;;; %define __?SECT?__ [section .text]
     0                                   ;;; %define __?DATE?__ "2019-10-15"
     0                                   ;;; %define __?DATE_NUM?__ 20191015
     0                                   ;;; %define __?TIME?__ "14:37:07"
     0                                   ;;; %define __?TIME_NUM?__ 143707
     0                                   ;;; %define __?UTC_DATE?__ "2019-10-15"
     0                                   ;;; %define __?UTC_DATE_NUM?__ 20191015
     0                                   ;;; %define __?UTC_TIME?__ "12:37:07"
     0                                   ;;; %define __?UTC_TIME_NUM?__ 123707
     0                                   ;;; %define __?POSIX_TIME?__ 1571143027
     0                                   ;;; %define __?OUTPUT_FORMAT?__ bin
     1                                  %idefine d dword
     1                                   ;;; %idefine d dword
     2
     3                                  %define _1digits_nocheck(d)     (((d)% 10)+'0')
     3                                   ;;; %define _1digits_nocheck(d) (((d)% 10)+'0')
     4                                  %xdefine _1digits(d)    (!!(d/10)*(1<<32)+  _1digits_nocheck(d))
     4                                   ;;; %define _1digits(d) (!!(dword/10)*(1<<32)+ (((dword)% 10)+'0'))
     5
     6                                  db _1digits(8)
     6          ******************       error: expression syntax error
$ cat test2.asm
%idefine d dword

%define _1digits_nocheck(d)     (((d)% 10)+'0')
%define _1digits(d)     (!!(d/10)*(1<<32)+  _1digits_nocheck(d))

db _1digits(8)
$ nasm test2.asm
$ nasm -Ls -Lp -l test2.lst test2.asm
$ cat test2.lst
     0                                   ;;; %define __?FILE?__
     0                                   ;;; %define __?LINE?__
     0                                   ;;; %define __?BITS?__
     0                                   ;;; %define __?PTR?__
     0                                   ;;; %define __?PASS?__ 2
     0                                   ;;; %define __?SECT?__
     0                                   ;;; %defalias __SECT__ __?SECT?__
     0                                   ;;; %define __?SECTALIGN_ALIGN_UPDATES_SECTION?__ 1
     0                                   ;;; %defalias __SECTALIGN_ALIGN_UPDATES_SECTION__ __?SECTALIGN_ALIGN_UPDATES_SECTION?__
     0                                   ;;; %define __?FLOAT_DAZ?__ nodaz
     0                                   ;;; %define __?FLOAT_ROUND?__ near
     0                                   ;;; %define __?FLOAT?__ __?FLOAT_DAZ?__,__?FLOAT_ROUND?__
     0                                   ;;; %defalias __FLOAT_DAZ__ __?FLOAT_DAZ?__
     0                                   ;;; %defalias __FLOAT_ROUND__ __?FLOAT_ROUND?__
     0                                   ;;; %defalias __FLOAT__ __?FLOAT?__
     0                                   ;;; %defalias __NASM_MAJOR__ __?NASM_MAJOR?__
     0                                   ;;; %defalias __NASM_MINOR__ __?NASM_MINOR?__
     0                                   ;;; %defalias __NASM_SUBMINOR__ __?NASM_SUBMINOR?__
     0                                   ;;; %defalias __NASM_PATCHLEVEL__ __?NASM_PATCHLEVEL?__
     0                                   ;;; %defalias __NASM_SNAPSHOT__ __?NASM_SNAPSHOT?__
     0                                   ;;; %defalias __NASM_VERSION_ID__ __?NASM_VERSION_ID?__
     0                                   ;;; %defalias __NASM_VER__ __?NASM_VER?__
     0                                   ;;; %defalias __OUTPUT_FORMAT__ __?OUTPUT_FORMAT?__
     0                                   ;;; %defalias __DEBUG_FORMAT__ __?DEBUG_FORMAT?__
     0                                   ;;; %defalias __DATE__ __?DATE?__
     0                                   ;;; %defalias __DATE_NUM__ __?DATE_NUM?__
     0                                   ;;; %defalias __TIME__ __?TIME?__
     0                                   ;;; %defalias __TIME_NUM__ __?TIME_NUM?__
     0                                   ;;; %defalias __UTC_DATE__ __?UTC_DATE?__
     0                                   ;;; %defalias __UTC_DATE_NUM__ __?UTC_DATE_NUM?__
     0                                   ;;; %defalias __UTC_TIME__ __?UTC_TIME?__
     0                                   ;;; %defalias __UTC_TIME_NUM__ __?UTC_TIME_NUM?__
     0                                   ;;; %defalias __POSIX_TIME__ __?POSIX_TIME?__
     0                                   ;;; %defalias __FILE__ __?FILE?__
     0                                   ;;; %defalias __LINE__ __?LINE?__
     0                                   ;;; %defalias __BITS__ __?BITS?__
     0                                   ;;; %defalias __PTR__ __?PTR?__
     0                                   ;;; %defalias __PASS__ __?PASS?__
     0                                   ;;; %idefine __?infinity?__ %?
     0                                   ;;; %idefine __?nan?__ %?
     0                                   ;;; %idefine __?qnan?__ %?
     0                                   ;;; %idefine __?snan?__ %?
     0                                   ;;; %idefine __?float8?__ %?
     0                                   ;;; %idefine __?float16?__ %?
     0                                   ;;; %idefine __?float32?__ %?
     0                                   ;;; %idefine __?float64?__ %?
     0                                   ;;; %idefine __?float80m?__ %?
     0                                   ;;; %idefine __?float80e?__ %?
     0                                   ;;; %idefine __?float128l?__ %?
     0                                   ;;; %idefine __?float128h?__ %?
     0                                   ;;; %idefine __?utf16?__ %?
     0                                   ;;; %idefine __?utf16le?__ %?
     0                                   ;;; %idefine __?utf16be?__ %?
     0                                   ;;; %idefine __?utf32?__ %?
     0                                   ;;; %idefine __?utf32le?__ %?
     0                                   ;;; %idefine __?utf32be?__ %?
     0                                   ;;; %idefine __?ilog2e?__ %?
     0                                   ;;; %idefine __?ilog2w?__ %?
     0                                   ;;; %idefine __?ilog2f?__ %?
     0                                   ;;; %idefine __?ilog2c?__ %?
     0                                   ;;; %idefalias __infinity__ __?infinity?__
     0                                   ;;; %idefalias __nan__ __?nan?__
     0                                   ;;; %idefalias __qnan__ __?qnan?__
     0                                   ;;; %idefalias __snan__ __?snan?__
     0                                   ;;; %idefalias __float8__ __?float8?__
     0                                   ;;; %idefalias __float16__ __?float16?__
     0                                   ;;; %idefalias __float32__ __?float32?__
     0                                   ;;; %idefalias __float64__ __?float64?__
     0                                   ;;; %idefalias __float80m__ __?float80m?__
     0                                   ;;; %idefalias __float80e__ __?float80e?__
     0                                   ;;; %idefalias __float128l__ __?float128l?__
     0                                   ;;; %idefalias __float128h__ __?float128h?__
     0                                   ;;; %idefalias __utf16__ __?utf16?__
     0                                   ;;; %idefalias __utf16le__ __?utf16le?__
     0                                   ;;; %idefalias __utf16be__ __?utf16be?__
     0                                   ;;; %idefalias __utf32__ __?utf32?__
     0                                   ;;; %idefalias __utf32le__ __?utf32le?__
     0                                   ;;; %idefalias __utf32be__ __?utf32be?__
     0                                   ;;; %idefalias __ilog2e__ __?ilog2e?__
     0                                   ;;; %idefalias __ilog2w__ __?ilog2w?__
     0                                   ;;; %idefalias __ilog2f__ __?ilog2f?__
     0                                   ;;; %idefalias __ilog2c__ __?ilog2c?__
     0                                   ;;; %define __?NASM_MAJOR?__ 2
     0                                   ;;; %define __?NASM_MINOR?__ 14
     0                                   ;;; %define __?NASM_SUBMINOR?__ 99
     0                                   ;;; %define __?NASM_PATCHLEVEL?__ 90
     0                                   ;;; %define __?NASM_VERSION_ID?__ 0020E635Ah
     0                                   ;;; %define __?NASM_VER?__ "2.15rc0"
     0                                   ;;; %define __?SECT?__ [section .text]
     0                                   ;;; %define __?DATE?__ "2019-10-15"
     0                                   ;;; %define __?DATE_NUM?__ 20191015
     0                                   ;;; %define __?TIME?__ "14:37:45"
     0                                   ;;; %define __?TIME_NUM?__ 143745
     0                                   ;;; %define __?UTC_DATE?__ "2019-10-15"
     0                                   ;;; %define __?UTC_DATE_NUM?__ 20191015
     0                                   ;;; %define __?UTC_TIME?__ "12:37:45"
     0                                   ;;; %define __?UTC_TIME_NUM?__ 123745
     0                                   ;;; %define __?POSIX_TIME?__ 1571143065
     0                                   ;;; %define __?OUTPUT_FORMAT?__ bin
     1                                  %idefine d dword
     1                                   ;;; %idefine d dword
     2
     3                                  %define _1digits_nocheck(d)     (((d)% 10)+'0')
     3                                   ;;; %define _1digits_nocheck(d) (((d)% 10)+'0')
     4                                  %define _1digits(d)     (!!(d/10)*(1<<32)+  _1digits_nocheck(d))
     4                                   ;;; %define _1digits(d) (!!(d/10)*(1<<32)+ _1digits_nocheck(d))
     5
     6 00000000 38                      db _1digits(8)
$ oldnasm -v
NASM version 2.14.03rc2 compiled on Aug 31 2019
$ oldnasm test.asm
$ oldnasm test2.asm
$ /usr/bin/nasm -v
NASM version 2.12.01
$ /usr/bin/nasm test.asm
$ /usr/bin/nasm test2.asm
$
Comment 1 H. Peter Anvin 2019-10-16 14:57:56 PDT
You are quite correct; I just checked in a fix into the master branch.
Comment 2 E. C. Masloch 2019-10-17 01:34:07 PDT
This fix breaks the common %xdefine usage of appending to a list. Here, nasm is https://repo.or.cz/nasm.git/commitdiff/18f413422221063d524f7a5b08bece5f8604af27 and patnasm is the same but with https://repo.or.cz/nasm.git/commitdiff/e86fa7fffd1789e3b9b2c584d4401dbb6fc92186 reverted.

$ cat test.asm
%define list "", ""
%xdefine list list, "abc", "123"
%xdefine list list, "def", "456"

%error list
$ nasm -v
NASM version 2.15rc0 compiled on Oct 17 2019
$ nasm test.asm
test.asm:5: error: list, "def", "456"
$ patnasm -v
NASM version 2.15rc0 compiled on Oct 17 2019
$ patnasm test.asm
test.asm:5: error: "", "", "abc", "123", "def", "456"
$ oldnasm -v
NASM version 2.14.03rc2 compiled on Aug 31 2019
$ oldnasm test.asm
test.asm:5: error: "", "", "abc", "123", "def", "456"
$
Comment 3 E. C. Masloch 2019-10-17 01:43:56 PDT
The erroneous behaviour is slightly different if the list smacro is a context-local macro:

$ cat test2.asm
%push ROOT
%define %$namelist "", ""
%xdefine %$namelist %$namelist, "abc", "123"
%error %$namelist
%pop
$ nasm test2.asm
test2.asm:4: error: "", "abc", "123"
$ patnasm test2.asm
test2.asm:4: error: "", "", "abc", "123"
$ oldnasm test2.asm
test2.asm:4: error: "", "", "abc", "123"
$ cat test3.asm
%define list "", ""
%xdefine list list, "abc", "123"

%error list
$ nasm test3.asm
test3.asm:4: error: list, "abc", "123"
$ patnasm test3.asm
test3.asm:4: error: "", "", "abc", "123"
$ oldnasm test3.asm
test3.asm:4: error: "", "", "abc", "123"
$
Comment 4 E. C. Masloch 2019-10-17 01:47:13 PDT
A second %xdefine to a context-local list smacro still picks up the first list entry plus the appended entries:

$ cat test4.asm
%push ROOT
%define %$namelist "", ""
%xdefine %$namelist %$namelist, "abc", "123"
%xdefine %$namelist %$namelist, "def", "456"
%error %$namelist
%pop
$ nasm test4.asm
test4.asm:5: error: "", "def", "456"
$ patnasm test4.asm
test4.asm:5: error: "", "", "abc", "123", "def", "456"
$ oldnasm test4.asm
test4.asm:5: error: "", "", "abc", "123", "def", "456"
$
Comment 5 E. C. Masloch 2019-10-24 00:50:09 PDT
With https://repo.or.cz/nasm.git/commitdiff/e91f5cc1322eed4da0de81656276e021bf352c3d building lDebug, building bootimg, building all lmacros tests, and building the tests listed in this bug all succeed. Binary files are the same as with an older NASM, listings differ slightly.